import { Request, Response, NextFunction } from 'express';
import knowledgeService from '@services/knowledge.service';
import { KnowledgeStatus, KnowledgeType } from '@database/models/Knowledge';
import logger from '@utils/logger';

/**
 * Knowledge Controller
 */
class KnowledgeController {
  /**
   * Get knowledge documents list
   */
  async getKnowledgeDocs(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const {
        search,
        category,
        tags,
        status,
        type,
        page = '1',
        pageSize = '20',
      } = req.query;

      const filter: any = {};

      if (search) filter.search = search as string;
      if (category) filter.category = category as string;
      if (tags) filter.tags = (tags as string).split(',').filter(t => t);
      if (status) filter.status = status as KnowledgeStatus;
      if (type) filter.type = type as KnowledgeType;

      const pageNum = parseInt(page as string, 10);
      const pageSizeNum = parseInt(pageSize as string, 10);

      const result = await knowledgeService.getKnowledgeDocs(filter, pageNum, pageSizeNum);

      res.status(200).json({
        success: true,
        data: result.docs,
        pagination: {
          current: pageNum,
          pageSize: pageSizeNum,
          total: result.total,
        },
      });
    } catch (error) {
      logger.error('Failed to get knowledge docs:', error as Error);
      next(error);
    }
  }

  /**
   * Get knowledge document by ID
   */
  async getKnowledgeDoc(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { id } = req.params;
      const { incrementView = 'true' } = req.query;

      const doc = await knowledgeService.getKnowledgeDocById(
        id,
        incrementView === 'true'
      );

      if (!doc) {
        res.status(404).json({
          success: false,
          message: 'Knowledge document not found',
        });
        return;
      }

      res.status(200).json({
        success: true,
        data: doc,
      });
    } catch (error) {
      logger.error(`Failed to get knowledge doc ${req.params.id}:`, error as Error);
      next(error);
    }
  }

  /**
   * Create knowledge document
   */
  async createKnowledgeDoc(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { title, content, summary, type, category, tags, status, relatedAlerts } = req.body;

      const userId = req.user?._id.toString();
      const userName = req.user?.email || 'Unknown User';

      if (!userId) {
        res.status(401).json({
          success: false,
          message: 'User not authenticated',
        });
        return;
      }

      const doc = await knowledgeService.createKnowledgeDoc({
        title,
        content,
        summary,
        type: type || KnowledgeType.SOLUTION,
        category,
        tags: tags || [],
        status: status || KnowledgeStatus.DRAFT,
        relatedAlerts: relatedAlerts || [],
        author: userId,
        authorName: userName,
      });

      res.status(201).json({
        success: true,
        data: doc,
        message: 'Knowledge document created successfully',
      });
    } catch (error) {
      logger.error('Failed to create knowledge doc:', error as Error);
      next(error);
    }
  }

  /**
   * Update knowledge document
   */
  async updateKnowledgeDoc(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { id } = req.params;
      const { title, content, summary, type, category, tags, relatedAlerts } = req.body;

      const userId = req.user?._id.toString();
      const userName = req.user?.email || 'Unknown User';

      const doc = await knowledgeService.updateKnowledgeDoc(id, {
        title,
        content,
        summary,
        type,
        category,
        tags,
        relatedAlerts,
      }, userId, userName);

      if (!doc) {
        res.status(404).json({
          success: false,
          message: 'Knowledge document not found',
        });
        return;
      }

      res.status(200).json({
        success: true,
        data: doc,
        message: 'Knowledge document updated successfully',
      });
    } catch (error) {
      logger.error(`Failed to update knowledge doc ${req.params.id}:`, error as Error);
      next(error);
    }
  }

  /**
   * Delete knowledge document
   */
  async deleteKnowledgeDoc(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { id } = req.params;

      const deleted = await knowledgeService.deleteKnowledgeDoc(id);

      if (!deleted) {
        res.status(404).json({
          success: false,
          message: 'Knowledge document not found',
        });
        return;
      }

      res.status(200).json({
        success: true,
        message: 'Knowledge document deleted successfully',
      });
    } catch (error) {
      logger.error(`Failed to delete knowledge doc ${req.params.id}:`, error as Error);
      next(error);
    }
  }

  /**
   * Publish knowledge document
   */
  async publishKnowledgeDoc(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { id } = req.params;

      const doc = await knowledgeService.publishKnowledgeDoc(id);

      if (!doc) {
        res.status(404).json({
          success: false,
          message: 'Knowledge document not found',
        });
        return;
      }

      res.status(200).json({
        success: true,
        data: doc,
        message: 'Knowledge document published successfully',
      });
    } catch (error) {
      logger.error(`Failed to publish knowledge doc ${req.params.id}:`, error as Error);
      next(error);
    }
  }

  /**
   * Archive knowledge document
   */
  async archiveKnowledgeDoc(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { id } = req.params;

      const doc = await knowledgeService.archiveKnowledgeDoc(id);

      if (!doc) {
        res.status(404).json({
          success: false,
          message: 'Knowledge document not found',
        });
        return;
      }

      res.status(200).json({
        success: true,
        data: doc,
        message: 'Knowledge document archived successfully',
      });
    } catch (error) {
      logger.error(`Failed to archive knowledge doc ${req.params.id}:`, error as Error);
      next(error);
    }
  }

  /**
   * Get categories
   */
  async getCategories(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const categories = await knowledgeService.getCategories();

      res.status(200).json({
        success: true,
        data: categories,
      });
    } catch (error) {
      logger.error('Failed to get categories:', error as Error);
      next(error);
    }
  }

  /**
   * Get popular documents
   */
  async getPopularDocs(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { limit = '10' } = req.query;
      const limitNum = parseInt(limit as string, 10);

      const docs = await knowledgeService.getPopularDocs(limitNum);

      res.status(200).json({
        success: true,
        data: docs,
      });
    } catch (error) {
      logger.error('Failed to get popular docs:', error as Error);
      next(error);
    }
  }

  /**
   * Ask AI question about knowledge base
   */
  async askAI(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { question, context } = req.body;

      if (!question) {
        res.status(400).json({
          success: false,
          message: 'Question is required',
        });
        return;
      }

      const answer = await knowledgeService.askAI(question, context);

      res.status(200).json({
        success: true,
        data: answer,
      });
    } catch (error) {
      logger.error('Failed to answer AI question:', error as Error);
      next(error);
    }
  }

  /**
   * Add rating to knowledge document
   */
  async addRating(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const { id } = req.params;
      const { rating, comment } = req.body;

      const userId = req.user?._id.toString();
      const userName = req.user?.email || 'Unknown User';

      if (!userId) {
        res.status(401).json({
          success: false,
          message: 'User not authenticated',
        });
        return;
      }

      if (!rating || rating < 1 || rating > 5) {
        res.status(400).json({
          success: false,
          message: 'Rating must be between 1 and 5',
        });
        return;
      }

      const doc = await knowledgeService.addRating(id, userId, userName, rating, comment);

      if (!doc) {
        res.status(404).json({
          success: false,
          message: 'Knowledge document not found',
        });
        return;
      }

      res.status(200).json({
        success: true,
        data: doc,
        message: 'Rating added successfully',
      });
    } catch (error) {
      logger.error(`Failed to add rating to knowledge doc ${req.params.id}:`, error as Error);
      next(error);
    }
  }
}

export default new KnowledgeController();
